package com.giscloud.dynamicsql.controller;

import cn.hutool.http.server.HttpServerResponse;
import cn.hutool.json.JSON;
import com.alibaba.fastjson.JSONObject;
import com.giscloud.commons.model.Result;
import com.giscloud.dynamicsql.entity.DynamicSqlCfg;
import com.giscloud.dynamicsql.service.DynamicSqlService;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@RestController
@RequestMapping("/giscloud/dynamicsql")
public class DynamicSqlController {

    //匹配 #{name,jdbcType=number} #{name ,jdbcType=number} #{name}
    private final static Pattern p=Pattern.compile("#\\{([A-Za-z0-9]+)[\\s|\\}|,]");

    @Autowired
    private DynamicSqlService dynamicSqlService;

    private String GET_HOST = "http://47.102.45.201:8085/giscloud/dynamicsql/get/";

    /**
     * 执行动态配置sql POST
     * @param params
     * @return
     */
    @RequestMapping(value = "/post/{urlType}", produces="application/json;charset=UTF-8")
    @ResponseBody
    public Result dynamicPost(@PathVariable("urlType") String urlType, @RequestBody(required=false) Map<String,Object> params) {
        return dynamicQuery(urlType,params);
    }

    /**
     * 执行动态配置sql GET
     * @param params
     * @return
     */
    @RequestMapping(value = "/get/{urlType}", produces="application/json;charset=UTF-8")
    @ResponseBody
    public Result dynamicGet(@PathVariable("urlType") String urlType,@RequestParam Map<String,Object> params) {
        return dynamicQuery(urlType,params);
    }

    private Result dynamicQuery(String urlType,Map<String,Object> params){
        DynamicSqlCfg dynamicSqlCfg = dynamicSqlService.queryDynamicSqlCfg(urlType);
        if(dynamicSqlCfg == null || StringUtils.isBlank(dynamicSqlCfg.getSql())){
            return Result.error("配置sql不存在！");
        }
        if(params == null){
            params = new HashMap<>();
        }else{
            //参数处理
            paramsProcess(params);
        }
        String dynamicSql = dynamicSqlCfg.getSql();
        if(dynamicSql.contains("[")) {
            dynamicSql = dynamicSql.replaceAll("\\[","&??").replaceAll("\\]","&");
        }
        String[] sqlStrs = dynamicSql.split("&");
        StringBuilder sb = new StringBuilder();
        for(String sqlStr : sqlStrs ){
            if(StringUtils.isNotBlank(sqlStr)){
                Matcher m=p.matcher(sqlStr);
                //发现是否是参数配置的sql片段
                if(m.find()) {
                    //未在[]中的包含参数设置的，为必填参数
                    if(!sqlStr.startsWith("??")){
                        if(params.get(m.group(1)) == null || StringUtils.isBlank(String.valueOf(params.get(m.group(1))))){
                            return Result.error(m.group(1) + "必填！");
                        }
                        //继续查找必填参数
                        while(m.find()){
                            if(params.get(m.group(1)) == null || StringUtils.isBlank(String.valueOf(params.get(m.group(1))))){
                                return Result.error(m.group(1) + "必填！");
                            }
                        }
                        sb.append(sqlStr + " ");
                    }else{
                        if(params.get(m.group(1)) != null && StringUtils.isNotBlank(String.valueOf(params.get(m.group(1))))){
                            sb.append(sqlStr.replace("??","") + " ");
                        }
                    }
                }else{
                    sb.append(sqlStr + " ");
                }
            }
        }
        dynamicSql = sb.toString();
        params.put("dynamicSql",dynamicSql);
        List<Map<String,Object>> list =  dynamicSqlService.dynamicQuery(params);
        return Result.success(list);
    }


    private void paramsProcess(Map<String,Object> params){
        Set<String> set = params.keySet();
        for(String key : set){
            String value = params.get(key) == null ? null:String.valueOf(params.get(key));
            //将纯数字类型，且key名称不以“Str”结尾的值转为 bigDecimal类型
            if(StringUtils.isNotBlank(value) && value.matches("^[1-9][0-9]*$") && !key.endsWith("Str")){
                params.put(key,new BigDecimal(value));
            }
        }
    }

    /**
     * 查询接口配置列表
     * @param module
     * @return
     */
    @RequestMapping(value = "/list/{module}")
    public void moduleList(@PathVariable("module") String module, HttpServletResponse response) {
        DynamicSqlCfg dynamicSqlCfg = new DynamicSqlCfg();
        if("all".equals(module)){
            dynamicSqlCfg.setModule(null);
        }else{
            dynamicSqlCfg.setModule(module);
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<html><head><title>配置化接口列表</title></head><body>");
        sb.append("<h3>配置化接口列表</h3>");
        sb.append("<div style='padding:0 40;'><p style='color:red;font-size:14px'>" +
                "说明：get接口通过‘?key=value’形式传参，post接口通过json格式传参;  接口的参数字段和返回结果字段说明，在详情中查看" +
                "</p></div>");
        List<DynamicSqlCfg> dynamicSqlCfgs = dynamicSqlService.queryDynamicSqlCfgList(dynamicSqlCfg);
        sb.append("<table border='0' style='padding:10 20;border-spacing:30px 10px;'><tr><th>模块</th><th>接口名称</th><th>GET访问</th><th>POST路径</th><th>接口详情</th></tr>");
        String tdStr = "<tr><td>{module}</td>" +
                "<td>{title}" +
                "</td><td><a href='../get/{urlType}' target='_blank'>/giscloud/dynamicsql/get/{urlType}</a></td>" +
                "</td><td>/giscloud/dynamicsql/post/{urlType}</a></td>" +
                "</td><td><a href='../get/{urlType}/info' target='_blank'>详情</a></td>" +
                "</tr>";

        if(CollectionUtils.isEmpty(dynamicSqlCfgs)){
            sb.append("查无接口！");
        }else {
            for (DynamicSqlCfg item : dynamicSqlCfgs) {
                sb.append(tdStr.replace("{module}", item.getModule() == null ? "" :  item.getModule())
                        .replace("{title}", item.getTitle() == null ? "" :  item.getTitle())
                        .replace("{urlType}", item.getUrlType() == null ? "" :  item.getUrlType()));
            }

        }
        sb.append("</table></body></html>");
        PrintWriter pw =null;
        response.setHeader("Content-Type","text/html;charset=UTF-8");
        try {
            pw = response.getWriter();
            pw.write(sb.toString());
            pw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            pw.close();
        }
    }

    /**
     * 查询接口配置列表
     * @param urlType
     * @return
     */
    @RequestMapping(value = "/get/{urlType}/info", produces="application/json;charset=UTF-8")
    @ResponseBody
    public List<Map<String,Object>> dynamicQueryInfo(@PathVariable("urlType") String urlType) {
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> resultMap = new HashMap<>();
        DynamicSqlCfg dynamicSqlCfg = dynamicSqlService.queryDynamicSqlCfg(urlType);
        if(dynamicSqlCfg == null){
            resultMap.put("msg","配置不存在！");
            list.add(resultMap);
            return list;
        }
        resultMap.put("接口名称",dynamicSqlCfg.getTitle());
        list.add(resultMap);
        resultMap = new HashMap<>();
        try {
            resultMap.put("参数说明", JSONObject.parse(dynamicSqlCfg.getParamsDesc()));
        } catch (Exception e) {
            resultMap.put("参数说明", dynamicSqlCfg.getParamsDesc());
        }
        list.add(resultMap);
        resultMap = new HashMap<>();
        try {
            resultMap.put("返回字段说明",JSONObject.parse(dynamicSqlCfg.getColumnsDesc()));
        } catch (Exception e) {
            resultMap.put("返回字段说明", dynamicSqlCfg.getParamsDesc());
        }
        list.add(resultMap);
        resultMap = new HashMap<>();
        resultMap.put("SQL语句",dynamicSqlCfg.getSql());
        list.add(resultMap);
        resultMap = new HashMap<>();
        resultMap.put("备注",dynamicSqlCfg.getDescription());
        list.add(resultMap);
        return list;
    }
}
